#include "syn_data.h"
#include "com_fun.h"

//守时机制共有3部分：
//	1、定时器CNT，由pps触发reset
//	2、定时器周期中断计数，不同步
//	3、定时器周期中断计数累积的秒，通信接收秒同步，同时重新累计计数

//当前守时时间
SYNT_TIME synd_time={0}; //系统时间，其中秒内为守时的整周期数
u32 synd_tick=0; //系统时间中秒内的tick累加数

u32 synd_pre_sec_in=0; //上次通信输入的秒
u32 synd_pre_sec_change=0; //上次通信输入的秒跳变时刻(0.1us)
u32 synd_pre_pps_time=10*1000*1000 * 10; //上次pps事件的时刻(0.1us)
u32 synd_pre_pps_tick=0; //上次pps事件的时刻的tick值

//S_SYN_10MS_PACK synd_buf[2]; //双缓存: G4的DMA没有双缓冲模式，只有环形模式
S_SYN_10MS_PACK synd_buf; //发送缓存
u16 synd_ring_buf[SYN_PACK_SIZE * 2]; //接收AD数据的环形缓存
u32 synd_buf_proc_ind = 0; //缓存处理指示

u32 synd_pre_utc = 0; //上次采集一包的起始时刻
u32 synd_pre_01us = 0; //上次采集一包的起始时刻(秒内0.1us)

//SYNT_TIME operator-(SYNT_TIME a, SYNT_TIME b) //两时间戳相减
//{
	//a.us01 -= b.us01;
	//if(a.us01 > 10*1000*1000) { a.sec -= 1; } //若出现溢出(超1秒)
	//a.sec -= b.sec;
	//return a;
//}
//主线程调用（通信接收）
void synd_sec_in_pro(u32 sec) //处理通信输入秒值
{
	if(sec != synd_pre_sec_in) //跟上次的不一样，发生了秒跳
	{
		synd_pre_sec_change = synd_time.us01;
		//通信输入的秒一定是比守时秒慢一点，但不会太多，所以可以直接覆盖
		synd_time.sec = sec;
		//检测是否可做时统
		if(synd_pre_sec_change - synd_pre_pps_time < 10*1000*10) //小于10ms(认为后收秒跳)
		{
			//这个pps是整秒，发生时的本地时间秒内值应为0，当前秒已经同步，秒内值减掉即可
			if(synd_tick >= synd_pre_pps_tick)
			{ //1.98收到pps，1.99收到秒跳，则此时为2.01，秒内值应改为1
				synd_tick -= synd_pre_pps_tick;
			}
			else //若已经经历了归零，需要加1轮
			{ //1.99收到pps，2.01收到秒跳，则此时为2.02，秒内值应改为2
				synd_tick = 10*1000*1000 - (synd_pre_pps_tick - synd_tick);
			}
			synd_time.us01 = synd_tick * SAMPLE_T_01US; //更新时间
		}
		synd_pre_pps_time = 10*1000*1000 * 10; //每次秒跳清除一下时间
	}
	synd_pre_sec_in = sec;
}
//中断调用
void synd_pps_INTR(void) //处理pps中断(10Hz)
{
	//此时TIM的CNT已经清零了，只需记录synd_time即可
	synd_pre_pps_tick = synd_tick;
	synd_pre_pps_time = synd_time.us01;
}
void synd_TIM_INTR(void) //处理定时器单个周期中断(12.8KHz)
{ //累加秒内计数值
	synd_tick++;
	if(synd_tick >= SAMPLE_F) //秒跳
	{
		synd_tick=0;
		synd_time.sec++;
	}
	synd_time.us01 = synd_tick * SAMPLE_T_01US;
}

void synd_in_half_INTR(u32 proc_ind) //输入0为DMA半满，1为完成
{
//计算时间戳
	synd_buf.utc = synd_pre_utc;
	synd_buf.us01 = synd_pre_01us; //

	synd_pre_utc = synd_time.sec; 
	synd_pre_01us = synd_time.us10; //将当前时刻作为下一包的时间
//发送
	synd_buf.syn = 0xaa;
	synd_buf.type = 1;
	synd_buf.ch_n = SYN_PACK_CH; //通道数量
	synd_buf.len = SYN_PACK_N; //等间隔的数据点数
	//确定环形缓存中的位置
	synd_buf_proc_ind = proc_ind;
	//从环形缓存中取得数据
	memcpy(synd_buf.d, synd_ring_buf + synd_buf_proc_ind*SYN_PACK_SIZE, SYN_PACK_SIZE*2);
	//发送
	synd_buf.sum = check_sum((u8*)&synd_buf, sizeof(synd_buf)-1);
	synd_send(synd_buf); //非阻塞发送
}

void synd_ini(void)
{

}
//SYNT_TIME synd_get_01us(void) //获取当前秒内的0.1us计数
//{
	//SYNT_TIME t;
//
	//OS_CLOSE_INT; //此函数应防止秒和us分开取导致的不同步
	//t.sec = synd_sec;
	//t.us01 = synd_01us_tick + TIM3->CNT*(0.00625f*10);
	//if(t.us01 > 10*1000*1000) t.us01 = 10*1000*1000-1;
	//OS_OPEN_INT;
//
	//return t;
//}
